package de.fhb.equakecamel;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.camel.Exchange;
import org.apache.camel.language.XPath;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.xml.sax.InputSource;

public class EnrichWithWeather {
	
	public void enrich(	Exchange _exchange,
			@XPath("/earthquake") String _message,
			@XPath("/earthquake/latitude/text()") String _latitude,
			@XPath("/earthquake/longitude/text()") String _longitude,
			@XPath("/earthquake/date/text()") String _date) {		
		
		if( !_message.isEmpty()) {
			double latitude = Double.parseDouble(_latitude);
			double longitude = Double.parseDouble(_longitude);		
			
			String weatherXML = requestWeather(latitude, longitude, _date.split(" ")[0] );
			
			String 	windSpeedInKmph		= null,
					windDirection		= null,
					weatherDesc			= null,
					tempMinC			= null,
					tempMaxC			= null;
			try {
				windSpeedInKmph = getXPathInformation(weatherXML, "/data/weather/windspeedKmph");
				windDirection 	= getXPathInformation(weatherXML, "/data/weather/winddirection");
				weatherDesc	 	= getXPathInformation(weatherXML, "/data/weather/weatherDesc");
				tempMinC 		= getXPathInformation(weatherXML, "/data/weather/tempMinC");
				tempMaxC		= getXPathInformation(weatherXML, "/data/weather/tempMaxC");
				
				String weatherAppendix =	"  <tempMinC>"+tempMinC+"</tempMinC>\n"+
				"  <tempMaxC>"+tempMaxC+"</tempMaxC>\n"+
				"  <windSpeedKmph>"+windSpeedInKmph+"</windSpeedKmph>\n"+
				"  <windDir>"+windDirection+"</windDir>\n"+
				"  <weatherDesc>"+weatherDesc+"</weatherDesc>\n"+
				"</earthquake>";

				String newMessage = _message.replace("</earthquake>", weatherAppendix);	
				
				_exchange.getOut().setBody(newMessage);
			
				// If an execption is throws the maximum free api key request is reached (500 / hour)
				// in this case nothing will append and the mesage wil be unenriched
			} catch (XPathExpressionException e) {
				_exchange.getOut().setBody(_message);
			} catch (UnsupportedEncodingException e) {
				_exchange.getOut().setBody(_message);
			}
		}
	}
	
	private String getXPathInformation(String xmlFile, String expression) throws XPathExpressionException, UnsupportedEncodingException{
		
		InputStream is = new ByteArrayInputStream(xmlFile.getBytes("UTF8")); 
		javax.xml.xpath.XPath xpath = XPathFactory.newInstance().newXPath();
		InputSource inputSource = new InputSource(is);
		
		return xpath.evaluate(expression, inputSource);
	}
	
	public String requestWeather(double latitude, double longitube, String date) {

		// be2d06c5eb134915112201 API-Key for www.worldweatheronline.com
		String hostline =  "http://www.worldweatheronline.com";
		
		 // Create an instance of HttpClient.
	    HttpClient client = new HttpClient();

	    // Create a method instance.
	    // date -> example: 2011-01-23  JJJJ-MM-TT / YYYY-MM-DD
	    GetMethod method = new GetMethod(hostline + "/feed/weather.ashx?key=be2d06c5eb134915112201&" +
				"q=" + latitude + "," + longitube + "&cc=no&date=" + date + "&format=xml");
	    
	    // Provide custom retry handler is necessary
	    method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
	    		new DefaultHttpMethodRetryHandler(3, false));

	    try {
	      // Execute the method.
	      int statusCode = client.executeMethod(method);

	      if (statusCode != HttpStatus.SC_OK) {
	        System.err.println("Method failed: " + method.getStatusLine());
	      }

	      // Read the response body.
	      byte[] responseBody = method.getResponseBody();

	      // Deal with the response.
	      // Use caution: ensure correct character encoding and is not binary data	      
	      return new String(responseBody);
	      
	    } catch (HttpException e) {
	      System.err.println("Fatal protocol violation: " + e.getMessage());
	      e.printStackTrace();
	    } catch (IOException e) {
	      System.err.println("Fatal transport error: " + e.getMessage());
	      e.printStackTrace();
	    } finally {
	      // Release the connection.
	      method.releaseConnection();
	    }  		
	    
	    return null;
	    
	}
}
